/*Ryan Ott
  08371740
  Assignment 5
*/
enum opcode{MOVE = 0, SWAP, CLR, JNZ, JZ, ADD, SUB, MULT, DIV, GET, PUT};
enum regis{ A = 0, R1, R2, R3, R4, R5, R6, R7};
enum lexeme{ INTEGER = 0, FLOAT, REGZ, OPCODE};
int toknum;
int lines;

struct vm_Program {
	struct vm_Instruction *inst;
	int ninsts;
};

/*The different values the token can take */
union value
{
	int i;
	float f;
	enum regis r;
	enum opcode op;
};

/*A token consists of its value, the type of the value, a pointer to the next token and the line number it was from */
struct token
{
	union value v;
	enum lexeme type;
	struct token *next;
	struct token *prev;
	int linenum;
};

struct vm_State{
	int regs[8];
	int IP;
};

typedef int (* vm_Opfxn)(struct vm_State*, union value a, union value b);

struct vm_Instruction {
        vm_Opfxn fxn;
        union value a;
        union value b;
};

/*a list of tokens with pointers to the front and back*/
struct list
{
	struct token *head;
	struct token *tail;
	struct token *front;
};

/*a constructor for a new token*/
struct token* new_Token(union value val, enum lexeme t, int l);

/*a constructor for a new list*/
struct list *new_list();

/*deletes the token passed*/
void delete_token(struct token *t);

/*Moves through the list and deletes each token before deleteing itself*/
void delete_list (struct list *ll);

/*Adds a token to the end of the list*/
void list_pushback(struct list *ll, struct token *t);
    
/*Removes a token from the front of the list*/
struct token token_popfront(struct list *ll);

/*creates a token from a string.  This analyzes any potential string and creates a token for it if the data is valid*/
struct token* tokenizer(char *s1, FILE* err, int line);
	
/*converts a token to a string*/
char* tokToString(struct token *t1, char* sout, char* lexeme,char* val);

void tokOut(struct list *ll, FILE *in, FILE *out, FILE *err);

/*accepts input file, output file and error file streams.  Seperates input into tokens, prints tokens to output and invalid input to error*/
struct list* lex(FILE* in, FILE* out, FILE* err);

	
				
		
		

   

